package ${packagePrefix}.infrastructure.repository;

import ${packagePrefix}.client.dto.query.${domainObjectName}ListQry;
import ${packagePrefix}.domain.model.${tableName?lower_case}.${domainObjectName};
import ${packagePrefix}.infrastructure.dataobject.${domainObjectName}DO;
import ${packagePrefix}.infrastructure.mapper.${domainObjectName}Mapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

class ${domainObjectName}RepositoryTest {

    @InjectMocks
    private ${domainObjectName}RepositoryImpl ${domainObjectName?uncap_first}Repository;

    @Mock
    private ${domainObjectName}Mapper ${domainObjectName?uncap_first}Mapper;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void shouldFindByIdSuccessfully() {
        // Given
        ${domainObjectName}DO ${domainObjectName?uncap_first}DO = new ${domainObjectName}DO();
        ${domainObjectName?uncap_first}DO.setId(1L);
        // Set other properties
        
        when(${domainObjectName?uncap_first}Mapper.selectById(1L)).thenReturn(${domainObjectName?uncap_first}DO);
        
        // When
        Optional<${domainObjectName}> result = ${domainObjectName?uncap_first}Repository.findById(1L);
        
        // Then
        assertTrue(result.isPresent());
        assertEquals(1L, result.get().getId());
        verify(${domainObjectName?uncap_first}Mapper).selectById(1L);
    }

    @Test
    void shouldReturnEmptyOptionalWhenNotFound() {
        // Given
        when(${domainObjectName?uncap_first}Mapper.selectById(1L)).thenReturn(null);
        
        // When
        Optional<${domainObjectName}> result = ${domainObjectName?uncap_first}Repository.findById(1L);
        
        // Then
        assertFalse(result.isPresent());
        verify(${domainObjectName?uncap_first}Mapper).selectById(1L);
    }

    @Test
    void shouldSaveNewEntitySuccessfully() {
        // Given
        ${domainObjectName} entity = new ${domainObjectName}();
        // Set properties but not ID
        
        when(${domainObjectName?uncap_first}Mapper.insert(any(${domainObjectName}DO.class))).thenAnswer(invocation -> {
            ${domainObjectName}DO ${domainObjectName?uncap_first}DO = invocation.getArgument(0);
            ${domainObjectName?uncap_first}DO.setId(1L);
            return 1;
        });
        
        // When
        Long id = ${domainObjectName?uncap_first}Repository.save(entity);
        
        // Then
        assertEquals(1L, id);
        verify(${domainObjectName?uncap_first}Mapper).insert(any(${domainObjectName}DO.class));
        verify(${domainObjectName?uncap_first}Mapper, never()).updateById(any(${domainObjectName}DO.class));
    }

    @Test
    void shouldUpdateExistingEntitySuccessfully() {
        // Given
        ${domainObjectName} entity = new ${domainObjectName}();
        entity.setId(1L);
        // Set other properties
        
        when(${domainObjectName?uncap_first}Mapper.updateById(any(${domainObjectName}DO.class))).thenReturn(1);
        
        // When
        Long id = ${domainObjectName?uncap_first}Repository.save(entity);
        
        // Then
        assertEquals(1L, id);
        verify(${domainObjectName?uncap_first}Mapper, never()).insert(any(${domainObjectName}DO.class));
        verify(${domainObjectName?uncap_first}Mapper).updateById(any(${domainObjectName}DO.class));
    }

    @Test
    void shouldFindByConditionSuccessfully() {
        // Given
        ${domainObjectName}ListQry qry = new ${domainObjectName}ListQry();
        // Set query parameters
        
        ${domainObjectName}DO ${domainObjectName?uncap_first}DO = new ${domainObjectName}DO();
        ${domainObjectName?uncap_first}DO.setId(1L);
        // Set other properties
        
        List<${domainObjectName}DO> ${domainObjectName?uncap_first}DOList = Collections.singletonList(${domainObjectName?uncap_first}DO);
        
        when(${domainObjectName?uncap_first}Mapper.selectByCondition(qry)).thenReturn(${domainObjectName?uncap_first}DOList);
        
        // When
        List<${domainObjectName}> result = ${domainObjectName?uncap_first}Repository.findByCondition(qry);
        
        // Then
        assertNotNull(result);
        assertEquals(1, result.size());
        assertEquals(1L, result.get(0).getId());
        verify(${domainObjectName?uncap_first}Mapper).selectByCondition(qry);
    }

    @Test
    void shouldDeleteByIdSuccessfully() {
        // Given
        when(${domainObjectName?uncap_first}Mapper.deleteById(1L)).thenReturn(1);
        
        // When
        ${domainObjectName?uncap_first}Repository.deleteById(1L);
        
        // Then
        verify(${domainObjectName?uncap_first}Mapper).deleteById(1L);
    }
} 